package com.loozb.thread4.queue1;

import com.google.common.collect.Queues;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 队列异步批量保存日志
 */
public class QueueService {

    /**
     * 一次插入500条
     */
    private static int MAX_INSERT_NUM = 10;

    /**
     * 等待超时时间(单位:秒)
     */
    private static int TIME_OUT = 5;

    /**
     * 日志队列
     */
    private BlockingQueue<SysLog> queue = new LinkedBlockingQueue<>();

    private volatile QueueThread queueThread = null;

    public boolean add(SysLog log) {
        if(queueThread == null) {
            startQueueThread();
        }
        return queue.add(log);
    }

    private synchronized void startQueueThread() {
        if(queueThread == null) {
            queueThread = new QueueThread();
            new Thread(queueThread).start();
        }
    }

    public class QueueThread implements Runnable {
        @Override
        public void run() {
            try {
                loop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void loop() throws InterruptedException {
        List<SysLog> willSend;
        SysLog sysLog = null;
        while (true) {
            willSend = new ArrayList<>(MAX_INSERT_NUM);
            sysLog = queue.take();//取不到值会阻塞，take会释放cpu
            willSend.add(sysLog);
            int i = 0;
            //如果小于MAX_INSERT_NUM数量，或则去队列里5秒都请求不到数据，那就
            while (++i < MAX_INSERT_NUM && (sysLog = queue.poll(TIME_OUT, TimeUnit.SECONDS)) != null) {
                willSend.add(sysLog);
            }

            send(willSend);
        }
    }

    private void send(List<SysLog> willSend) {
        System.out.println("发送"+willSend.size()+"条消息");
        System.out.println("=============发送完成========");
    }

    /**
     * 模拟第三方调用add
     * @param args
     */
    public static void main(String[] args) {
        QueueService queueService = new QueueService();

        SysLog log = null;
        for (int i = 0; i < 11; i++) {
            try {
                log = new SysLog();
                log.setIdx(i + "");
                queueService.add(log);
                long time = (long) (Math.random()*1000);
                Thread.sleep(time);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
